/**
 * AssetBundle管理类
 */
export default class BundleMgr {
    private static _instance: BundleMgr = null
    public static get instance() {
        if (!this._instance) {
            this._instance = new BundleMgr()
        }
        return this._instance
    }

    /** 资产包Map <bundleName, bundle>*/
    private _bundleMap: Map<string, cc.AssetManager.Bundle> = new Map()

    /**
     * 获取预制
     * @param bundleName 包名
     * @param prefabName 预制名
     */
    async getPrefab(bundleName: string, prefabName: string) {
        // 获取包
        let bundle = await this._getBundle(bundleName)
        // 获取预制
        let prefab = await this._getPrefab(bundle, prefabName)
        return prefab
    }

    /**
     * 获取包
     * @param bundleName 包名
     */
    private async _getBundle(bundleName: string) {
        let bundle = this._bundleMap.get(bundleName)
        if (!bundle) {
            // 加载包
            bundle = await this._loadBundle(bundleName)
            this._bundleMap.set(bundleName, bundle)
        }
        return bundle
    }

    /**
     * 加载包
     * @param bundleName 包名
     */
    private async _loadBundle(bundleName: string): Promise<cc.AssetManager.Bundle> {
        return new Promise<cc.AssetManager.Bundle>(resolve => {
            cc.assetManager.loadBundle(bundleName, (err, bundle) => {
                resolve(bundle)
            })
        })
    }

    /**
     * 获取预制
     * @param bundle 包
     * @param prefabName 预制名
     */
    private async _getPrefab(bundle: cc.AssetManager.Bundle, prefabName: string) {
        let prefab: cc.Prefab = null
        if (bundle) {
            prefab = bundle.get(prefabName, cc.Prefab)
            if (!prefab) {
                prefab = await this._loadPrefab(bundle, prefabName)
            }
        }
        return prefab
    }

    /**
     * 加载预制
     * @param bundle 包
     * @param prefabName 预制名
     */
    private async _loadPrefab(bundle: cc.AssetManager.Bundle, prefabName: string) {
        return new Promise<cc.Prefab>(resolve => {
            bundle.load(prefabName, cc.Prefab, function (err, prefab: cc.Prefab) {
                resolve(prefab)
            })
        })
    }
}
